package com.giantlizard.cloud.base.utils;


import com.giantlizard.cloud.base.baseService.ITreeNode;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 树形结构工具类
 */
public class TreeUtils {

    /**
     * 构建树形结构（默认按ID升序）
     *
     * @param list 源数据集合
     * @param rootId 根节点ID
     * @param <T> 节点类型
     * @param <I> ID类型
     * @return 树形结构列表
     */
    public static <T extends ITreeNode<T, I>, I> List<T> buildTree(List<T> list, I rootId) {
        return buildTree(list, rootId, null, true);
    }

    /**
     * 构建树形结构（支持排序）
     *
     * @param list 源数据集合
     * @param rootId 根节点ID
     * @param sortField 排序字段（为空则按ID排序）
     * @param isAsc 是否升序（true升序，false降序）
     * @param <T> 节点类型
     * @param <I> ID类型
     * @return 树形结构列表
     */
    public static <T extends ITreeNode<T, I>, I> List<T> buildTree(List<T> list, I rootId, String sortField, boolean isAsc) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }

        // 将列表转换为Map，key为节点ID
        Map<I, T> nodeMap = list.stream().collect(Collectors.toMap(T::getId, Function.identity()));
        List<T> result = new ArrayList<>();

        for (T node : list) {
            I parentId = node.getParentId();
            if (Objects.equals(rootId, parentId)) {
                // 根节点直接添加到结果列表
                result.add(node);
            } else {
                // 非根节点添加到父节点的子节点列表中
                T parentNode = nodeMap.get(parentId);
                if (parentNode != null) {
                    if (parentNode.getChildren() == null) {
                        parentNode.setChildren(new ArrayList<>());
                    }
                    parentNode.getChildren().add(node);
                }
            }
        }

        // 对树进行排序
        sortTree(result, sortField, isAsc);

        return result;
    }

    /**
     * 构建树形结构（支持自定义根节点ID判断逻辑和排序）
     *
     * @param list 源数据集合
     * @param rootPredicate 根节点判断函数
     * @param sortField 排序字段（为空则按ID排序）
     * @param isAsc 是否升序（true升序，false降序）
     * @param <T> 节点类型
     * @param <I> ID类型
     * @return 树形结构列表
     */
    public static <T extends ITreeNode<T, I>, I> List<T> buildTree(List<T> list, Function<I, Boolean> rootPredicate,
                                                                   String sortField, boolean isAsc) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }

        Map<I, T> nodeMap = list.stream().collect(Collectors.toMap(T::getId, Function.identity()));
        List<T> result = new ArrayList<>();

        for (T node : list) {
            I parentId = node.getParentId();
            if (rootPredicate.apply(parentId)) {
                result.add(node);
            } else {
                T parentNode = nodeMap.get(parentId);
                if (parentNode != null) {
                    if (parentNode.getChildren() == null) {
                        parentNode.setChildren(new ArrayList<>());
                    }
                    parentNode.getChildren().add(node);
                }
            }
        }

        // 对树进行排序
        sortTree(result, sortField, isAsc);

        return result;
    }

    /**
     * 对树形结构进行排序
     *
     * @param list 要排序的列表
     * @param sortField 排序字段
     * @param isAsc 是否升序
     * @param <T> 节点类型
     */
    private static <T extends ITreeNode<T, ?>> void sortTree(List<T> list, String sortField, boolean isAsc) {
        if (list == null || list.isEmpty()) {
            return;
        }

        // 对当前层级进行排序
        list.sort((o1, o2) -> {
            try {
                // 如果未指定排序字段，则默认按ID排序
                String fieldName = StringUtils.hasText(sortField) ? sortField : "id";
                Field field = getField(o1.getClass(), fieldName);
                if (field == null) {
                    return 0;
                }

                field.setAccessible(true);
                Comparable val1 = (Comparable) field.get(o1);
                Comparable val2 = (Comparable) field.get(o2);

                if (val1 == null) {
                    return isAsc ? -1 : 1;
                }
                if (val2 == null) {
                    return isAsc ? 1 : -1;
                }

                return isAsc ? val1.compareTo(val2) : val2.compareTo(val1);
            } catch (Exception e) {
                return 0;
            }
        });

        // 递归对子节点进行排序
        for (T node : list) {
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                sortTree(node.getChildren(), sortField, isAsc);
            }
        }
    }

    /**
     * 获取类的字段（包括父类字段）
     *
     * @param clazz 类
     * @param fieldName 字段名
     * @return 字段对象
     */
    private static Field getField(Class<?> clazz, String fieldName) {
        Field field = null;
        while (clazz != null && field == null) {
            try {
                field = clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            }
        }
        return field;
    }
}